package com.xuecheng.content.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CoursePubDTO;
import com.xuecheng.api.content.model.dto.CourseTeacherDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.system.model.dto.CourseCategoryDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.content.agent.SystemApiAgent;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.convert.CoursePubConvert;
import com.xuecheng.content.convert.CourseTeacherConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.entity.CoursePub;
import com.xuecheng.content.entity.CourseTeacher;
import com.xuecheng.content.mapper.CoursePubMapper;
import com.xuecheng.content.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * <p>
 * 课程发布 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CoursePubServiceImpl extends ServiceImpl<CoursePubMapper, CoursePub> implements CoursePubService {

    @Autowired
    private SystemApiAgent systemApiAgent;

    @Autowired
    private CourseMarketService courseMarketService;
    @Autowired
    private CourseBaseService courseBaseService;
    @Autowired
    private TeachplanService teachplanService;
    @Autowired
    private CourseTeacherService courseTeacherService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Value("${rocketmq.massage.topic}")
    private String msgTopic;

    /**
     * <p>
     * 生成课程预览页面数据
     * </p>
     *
     * @param courseId  课程id
     * @param companyId 机构id
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> preview(Long courseId, Long companyId) {

        //生成或修改课程发布信息
        CoursePub coursePub = createCoursePub(courseId, companyId, false, false);
        CoursePubDTO coursePubDTO = CoursePubConvert.INSTANCE.entity2dto(coursePub);
        //生成DataMap数据
        return generateDataMap(coursePubDTO);
    }


    /**
     * <p>
     *
     * </p>
     *
     * @param courseId  课程id
     * @param companyId 机构id
     * @return void
     */
    @Override
    @Transactional
    public void publish(Long courseId, Long companyId) {
        //判断传入参数
        CourseBase courseBase = courseBaseService.getById(courseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        if (!ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //不能为已删除的课程
        if (courseBase.getStatus() == 0) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
        //发送事务消息,课程基本信息id
        Message<Long> message = MessageBuilder.withPayload(courseId).build();

        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(msgTopic, message, null);

        if (sendResult.getLocalTransactionState() == LocalTransactionState.COMMIT_MESSAGE) {
            log.info("发送事务消息成功，课程信息为 {} topic为{}",
                    courseId,
                    sendResult.getMessageQueue()
            );
        } else {

            log.error("发送事务消息失败，课程信息为 {}", courseId);
        }
    }

    @Transactional
    @Override
    public void createOrModifyCoursePub(Long courseId) {

        this.createCoursePub(courseId, null, true, false);

    }

    private Map<String, Object> generateDataMap(CoursePubDTO coursePub) {
        Map<String, Object> map = new HashMap<>();

        map.put("coursePub", coursePub);
        String market = coursePub.getMarket();
        CourseMarket courseMarket = JSON.parseObject(market, CourseMarket.class);
        map.put("courseMarket", courseMarket);
        String teachplan = coursePub.getTeachplan();
        TeachplanDTO teachplanNode = JSON.parseObject(teachplan, TeachplanDTO.class);
        map.put("courseTeachModeEnums", CourseModeEnum.values());
        map.put("teachplanNode", teachplanNode);

        return map;
    }

    private CoursePub createCoursePub(Long courseId, Long companyId, boolean isPub, boolean isAudit) {

        //判断传入参数
        CourseBase courseBase = courseBaseService.getById(courseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        if (!isPub && isAudit) {
            if (!ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)) {
                ExceptionCast.cast(CommonErrorCode.E_100108);
            }
        }

        //不能为已删除的课程
        if (courseBase.getStatus() == 0) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
        RestResponse<CourseCategoryDTO> mtResp = systemApiAgent.getCourseCategoryById(courseBase.getMt());
        RestResponse<CourseCategoryDTO> stResp = systemApiAgent.getCourseCategoryById(courseBase.getSt());
        if (!mtResp.isSuccessful() || !stResp.isSuccessful()) {
            ExceptionCast.cast(CommonErrorCode.E_100106);
        }

        //课程基本信息复制到课程发布
        CoursePub coursePub = CourseBaseConvert.INSTANCE.courseBaseToCoursePub(courseBase);
        //远程调用查询课程分类信息
        coursePub.setMtName(mtResp.getResult().getName());
        coursePub.setStName(stResp.getResult().getName());

        //课程营销信息复制到课程发布
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = Wrappers.lambdaQuery(CourseMarket.class)
                .eq(CourseMarket::getCourseId, courseId);
        CourseMarket courseMarket = courseMarketService.getOne(marketQueryWrapper);

        coursePub.setCharge(courseMarket.getCharge());
        coursePub.setPrice(courseMarket.getPrice());
        String marketJsonStr = JSON.toJSONString(courseMarket);
        coursePub.setMarket(marketJsonStr);
        TeachplanDTO teachplanDTO;
        //课程计划信息
        if (isPub || isAudit) {
            teachplanDTO = teachplanService.queryTreeNodes(courseId, null);
        } else {
            teachplanDTO = teachplanService.queryTreeNodes(courseId, companyId);
        }
        String teachplanJsonStr = JSON.toJSONString(teachplanDTO);
        coursePub.setTeachplan(teachplanJsonStr);
        //课程教师信息

        LambdaQueryWrapper<CourseTeacher> teacherQueryWrapper = Wrappers.lambdaQuery(CourseTeacher.class)
                .eq(CourseTeacher::getCourseId, courseId);
        List<CourseTeacher> teacherList = courseTeacherService.getBaseMapper().selectList(teacherQueryWrapper);
        List<CourseTeacherDTO> teacherDTOList = CourseTeacherConvert.INSTANCE.courseTeacherToDTOList(teacherList);

        String teacherJsonStr = JSON.toJSONString(teacherDTOList);
        coursePub.setTeachers(teacherJsonStr);
        //查询课程发布表是否有数据
        LambdaQueryWrapper<CoursePub> pubLambdaQueryWrapper = Wrappers.lambdaQuery(CoursePub.class).eq(CoursePub::getCourseId, courseId);

        CoursePub pubInDb = this.getOne(pubLambdaQueryWrapper);
        if (!ObjectUtils.isEmpty(pubInDb)) {
            coursePub.setId(pubInDb.getId());
        }
        //此处不修改发布状态,生产静态页面后在修改
        //if (isPub) {
        //    coursePub.setIsPub(0);
        //}
        boolean result = this.saveOrUpdate(coursePub);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120204);
        }
        //如果为发布操作，修改课程基本信息里的审核状态为已发布
        if (isPub && !isAudit) {
            LambdaUpdateWrapper<CourseBase> updateWrapper = Wrappers.lambdaUpdate(CourseBase.class)
                    .eq(CourseBase::getId, courseId)
                    .set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())
                    .set(CourseBase::getChangeDate, null);
            boolean update = courseBaseService.update(updateWrapper);
            if (!update) {
                ExceptionCast.cast(ContentErrorCode.E_120017);
            }
        }
        return coursePub;
    }


    @Override
    public RestResponse<CoursePubDTO> getCoursePubById(Long coursePubId) {

        CoursePub coursePub = this.getById(coursePubId);
        CoursePubDTO coursePubDTO = CoursePubConvert.INSTANCE.entity2dto(coursePub);

        return RestResponse.success(coursePubDTO);
    }


    @Autowired
    private CoursePubMapper coursePubMapper;

    /**
     * Feign调用， 根据教育机构id查询课程集合
     *
     * @param companyId 机构id
     */
    @Override
    public RestResponse<List<CoursePubDTO>> getCoursePubByCompanyId(Long companyId) {

        LambdaQueryWrapper<CoursePub> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CoursePub::getCompanyId, companyId);
        List<CoursePub> coursePubs = coursePubMapper.selectList(wrapper);
        List<CoursePubDTO> coursePubDTOS = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(coursePubs)) {
            coursePubDTOS = CoursePubConvert.INSTANCE.entitys2dtos(coursePubs);
        }
        return RestResponse.success(coursePubDTOS);
    }

    /**
     * <p>
     * 远端调用查询 课程发布信息
     * </p>
     *
     * @param courseId 课程id
     * @return RestResponse<CoursePubDTO>
     */
    @Override
    public RestResponse<CoursePubDTO> getCoursePubByCourseId(Long courseId) {

        LambdaQueryWrapper<CoursePub> queryWrapper = Wrappers.lambdaQuery(CoursePub.class)
                .eq(CoursePub::getCourseId, courseId);
        CoursePub coursePub = this.getOne(queryWrapper);

        CoursePubDTO coursePubDTO = null;
        if (!ObjectUtils.isEmpty(coursePub)) {
            coursePubDTO = CoursePubConvert.INSTANCE.entity2dto(coursePub);
        }
        return RestResponse.success(coursePubDTO);
    }

    /**
     * 运营平台审核课程预览
     *
     * @param courseBaseId
     * @return
     */
    @Override
    public Map<String, Object> auditPreview(Long courseBaseId) {

        //生成或修改课程发布信息
        CoursePub coursePub = createCoursePub(courseBaseId, null, false, true);
        CoursePubDTO coursePubDTO = CoursePubConvert.INSTANCE.entity2dto(coursePub);
        //生成DataMap数据
        return generateDataMap(coursePubDTO);
    }
}
